#! venv/Scripts/python
# -*- coding: utf-8 -*-
import sys
import pygame
import time
import threading
import xml.etree.ElementTree as Et

import Zhc_Control
import Zhc_Maps
import Zhc_Human
import Zhc_Skill
import Zhc_Fight

GlobalKeys = {
    "StartPush": True,
    "Count": 1,
    "DoSomething": 0,
    "DoSomethingDef": "",
    "DoSomethingData": "",
    "is_fight": 0,
    "select_human": "",
    "player_fight_hp":0,
    "human_fight_hp":0
}

# 调用地图原理
# * 地图最终调用是使用Mapcase调用的，这个地点包含了所有初始化的地图
# * 背景和按钮组是分离的，只是人对触发区域进行了设置。
# 1、初次进入时，默认会进入大地图，因为 SelectMap 的值是WorldMap
# 2、ReturnPlaceType是用来识别点击区域的，使用的时候会触发相应的函数

MapUrl = {
    "WorldMap": "map/WorldMap.jpg",
    "MenPai1": "map/MenPai1.jpg",
    "ShowMessage": "map/ShowMessage.jpg",
    "fight": "map/fight.jpg",
    "sprite": "picture/button/human.jpg"
}

# 初始化所有地图
WorldMap = Zhc_Maps.BaseMapClass(img_url=MapUrl["WorldMap"])
MenPai1 = Zhc_Maps.BaseMapClass(img_url=MapUrl["MenPai1"])
ShowMessage = Zhc_Maps.BaseMapClass(img_url=MapUrl["ShowMessage"])
fight_map = Zhc_Maps.BaseMapClass(img_url=MapUrl["fight"])

MapCase = {
    "SelectMap": "WorldMap",
    "LastMap": "WorldMap",
    "WorldMap": WorldMap,
    "MenPai1": MenPai1,
    "ShowMessage": ShowMessage,
    "fight": fight_map
}
# 在这里预设一个字典，在IniHuman里将其初始化
Human = {}
# 在这里预设一个字典，在IniSkill里将其初始化
Skill = {}
# 地图的块，以及名称，及触发的类型,以及触发的id
# 0代表地图跳转，1代表函数触发,2代表需要同时跳转地图和触发函数
# 如果出现2类型，那么调用列表下标为0的函数,["方法名称","参数"]，调下标为2的地图
# 触发事件，使用全局全局按钮开关控制的，GlobalKeys["DoSomething"],如果是2，将方法名称传到此处，然后在MainWindow里执行
# 如果出现3类型，那么仅调用函数,函数为下标为0的名称
MapPlace = {
    "WorldMap": {
        (100, 100): ["地区1", 0, "MenPai1"],
        (150, 250): ["地区2", 0, "MenPai1"],
        (400, 200): ["地区3", 0, "MenPai1"],
        (50, 450): ["地区4", 0, "MenPai1"],
        (300, 400): ["地区5", 0, "MenPai1"],
        (500, 450): ["地区6", 0, "MenPai1"],

        (600, 575): [["ShowMessage", "player"], 2, "ShowMessage"],
    },
    "MenPai1": {
        (200, 200): [["ShowMessage", "长老"], 2, "ShowMessage"],
        (350, 200): [["ShowMessage", "护法"], 2, "ShowMessage"],
        (200, 350): [["ShowMessage", "弟子"], 2, "ShowMessage"],
        (350, 350): [["ShowMessage", "外门"], 2, "ShowMessage"],
        (500, 500): ["返回", 0, "WorldMap"],
    },
    "ShowMessage": {
        (500, 250): ["getstrong", 3, "getstrong"],
        (500, 300): [["fight", "任何人"], 2, "fight"],
        (500, 350): ["levelup", 3, "levelup"],
        (0, 150): ["消失", 1, "Des"],
        (550, 150): ["Back", 1, "Back"]
    },
    "fight": {}
}


def IniHuman():
    """
    对人物初始化
    :return: 字典，key为名称，value为Zhc_Human的实例
    """
    human_message = {}
    player = Zhc_Human.HummanBaseClass()
    Human["player"] = player
    tree = Et.parse('human.xml')
    root = tree.getroot()
    for child in root:
        human_message[child.find("name").text] = {
            "Level": child.find("Level").text,
            "player_sex": child.find("player_sex").text,
            "max_hp": child.find("max_hp").text,
            "max_mp": child.find("max_mp").text,
            "duanti": child.find("duanti").text,
            "lianqi": child.find("lianqi").text,
            "shenshi": child.find("shenshi").text,
            "yuqi": child.find("yuqi").text,
            "shufa": child.find("shufa").text,
            "guanchuan": child.find("guanchuan").text,
            "huti": child.find("huti").text,
        }
    for i in human_message:
        Human[i] = Zhc_Human.HummanBaseClass()
        Human[i].SetBaseData(human_message[i]["Level"], i, human_message[i]["player_sex"], human_message[i]["max_hp"],
                             human_message[i]["max_mp"], human_message[i]["duanti"], human_message[i]["lianqi"],
                             human_message[i]["shenshi"], )
        Human[i].SetFeatData(human_message[i]["yuqi"], human_message[i]["shufa"], human_message[i]["guanchuan"],
                             human_message[i]["huti"])


def IniSkill():
    """
    对技能初始化
    :return: 字典，key为名称，value为Zhc_Skill的实例
    """
    skill_message = {}
    # 从xml文件中读取，用getroot获取根节点，根节点也是Element对象
    tree = Et.parse('skills.xml')
    root = tree.getroot()
    # 打印根节点的标签和属性
    for child in root:
        skill_message[child.find("name").text] = {
            "type": child.find("type").text,
            "coe": child.find("coe").text,
            "time": child.find("time").text,
            "cost": child.find("cost").text,
        }
    for i in skill_message:
        Skill[i] = Zhc_Skill.SkillClass()
        Skill[i].set_num(i, skill_message[i]["type"], skill_message[i]["coe"], skill_message[i]["cost"])


def WriteText(root_surface, text, x, y):
    """
    用以在面板上写数据
    :param root_surface:
    :param text:
    :param x:
    :param y:
    :return:
    """
    text_font = pygame.font.Font("temp/simsun.ttc", 15)
    text = text_font.render(text, True, (0, 0, 0))
    root_surface.blit(text, (x + 2, y + 17))


def DrewOnlyPlayerMain(root_surface):
    # # 姓名
    WriteText(root_surface, Human["player"].player_name, 670, 50)
    # 等级
    WriteText(root_surface, "等级", 670, 75)
    WriteText(root_surface, str(Human["player"].Level), 710, 75)
    # 最大生命值
    WriteText(root_surface, "生命", 620, 140)
    WriteText(root_surface, str(Human["player"].max_hp), 660, 140)
    # 最大法力值
    WriteText(root_surface, "真气", 700, 140)
    WriteText(root_surface, str(Human["player"].max_mp), 740, 140)
    # 锻体
    WriteText(root_surface, "锻体", 620, 170)
    WriteText(root_surface, str(Human["player"].duanti), 660, 170)
    # 练气
    WriteText(root_surface, "练气", 700, 170)
    WriteText(root_surface, str(Human["player"].lianqi), 740, 170)
    # 神识
    WriteText(root_surface, "神识", 620, 200)
    WriteText(root_surface, str(Human["player"].shenshi), 660, 200)
    #
    # 御器攻击
    WriteText(root_surface, "御器", 700, 200)
    WriteText(root_surface, str(Human["player"].yuqi), 740, 200)
    # 术法攻击
    WriteText(root_surface, "术法", 620, 230)
    WriteText(root_surface, str(Human["player"].shufa), 660, 230)
    # 真气贯穿
    WriteText(root_surface, "贯穿", 700, 230)
    WriteText(root_surface, str(Human["player"].guanchuan), 740, 230)
    # 真气护体
    WriteText(root_surface, "护体", 620, 260)
    WriteText(root_surface, str(Human["player"].huti), 660, 260)


def DrewHumanMessage(root_surface, name):
    # 姓名
    WriteText(root_surface, "姓名", 50, 200)
    WriteText(root_surface, str(Human[name].player_name), 100, 200)
    # 等级
    WriteText(root_surface, "等级", 50, 250)
    WriteText(root_surface, str(Human[name].Level), 110, 250)
    # 最大生命值
    WriteText(root_surface, "生命值", 50, 300)
    WriteText(root_surface, str(Human[name].max_hp), 110, 300)
    # 最大法力值
    WriteText(root_surface, "法力值", 50, 350)
    WriteText(root_surface, str(Human[name].max_mp), 110, 350)
    # 锻体
    WriteText(root_surface, "锻体", 150, 250)
    WriteText(root_surface, str(Human[name].duanti), 210, 250)
    # 练气
    WriteText(root_surface, "练气", 150, 300)
    WriteText(root_surface, str(Human[name].lianqi), 210, 300)
    # 神识
    WriteText(root_surface, "神识", 150, 350)
    WriteText(root_surface, str(Human[name].shenshi), 210, 350)

    # 御器攻击
    WriteText(root_surface, "御器", 250, 200)
    WriteText(root_surface, str(Human[name].yuqi), 310, 200)
    # 术法攻击
    WriteText(root_surface, "术法", 250, 250)
    WriteText(root_surface, str(Human[name].shufa), 310, 250)
    # 真气贯穿
    WriteText(root_surface, "贯穿", 250, 300)
    WriteText(root_surface, str(Human[name].guanchuan), 310, 300)
    # 真气护体
    WriteText(root_surface, "护体", 250, 350)
    WriteText(root_surface, str(Human[name].huti), 310, 350)

    # 按钮
    WriteText(root_surface, "传授", 500, 250)
    WriteText(root_surface, "切磋", 500, 300)
    WriteText(root_surface, "学习", 500, 350)


def ReturnPlaceDef(temp_dir, pos):
    for i in temp_dir.keys():
        if (i[0] <= pos[0] <= i[0] + 50) and (i[1] <= pos[1] <= i[1] + 50):
            print("返回函数为", temp_dir[i][0])
            return temp_dir[i][0]


def ReturnPlaceType(temp_dir, pos):
    """
    返回点击的类型
    :param temp_dir:地图的坐标表
    :param pos:事件发生的位置
    :return:
    """
    for i in temp_dir.keys():
        if (i[0] <= pos[0] <= i[0] + 50) and (i[1] <= pos[1] <= i[1] + 50):
            print("此项触发类型为", temp_dir[i][1])
            return temp_dir[i][1]


def ReturnPlaceName(temp_dir, pos):
    """
    返回点击的地图名称
    :param temp_dir:
    :param pos:
    :return:
    """
    for i in temp_dir.keys():
        if (i[0] <= pos[0] <= i[0] + 50) and (i[1] <= pos[1] <= i[1] + 50):
            print("返回地图", temp_dir[i][2])
            return temp_dir[i][2]


def Fightone(root_surface, human_name):
    """
    被调用，在此计算伤害数据
    :param root_surface:
    :param human_name:
    :return:
    """
    end_time = 0
    player = Human["player"]
    fight_human = Human[human_name]
    GlobalKeys["player_fight_hp"] = int(player.max_hp)
    GlobalKeys["human_fight_hp"] = int(fight_human.max_hp)


    while (GlobalKeys["player_fight_hp"] > 0) and (GlobalKeys["human_fight_hp"] > 0):
        GlobalKeys["player_fight_hp"] -= int(fight_human.yuqi)
        GlobalKeys["human_fight_hp"] -= int(player.yuqi)
        time.sleep(1)
        print("玩家生命值剩余", GlobalKeys["player_fight_hp"], "对手生命值剩余", GlobalKeys["human_fight_hp"])
    print("战斗完成")


    # 战斗结束
    while end_time <=100:
        WriteText(root_surface, "战斗结束", 250, 150)
        end_time += 0.1

    GlobalKeys["is_fight"] = 0
    GlobalKeys["DoSomething"] = 0
    MapCase["SelectMap"] = "WorldMap"

def Fightsprite(root_face,human_name):
    click_time = 0
    player_sprite = Zhc_Fight.GameSprite(300,250)

    human_sprite = Zhc_Fight.GameSprite(200, 250)
    groups = pygame.sprite.Group()
    groups.add(human_sprite,player_sprite)
    while GlobalKeys["is_fight"] == 1:
        WriteText(root_face, str(GlobalKeys["player_fight_hp"]), 200, 170)
        WriteText(root_face, str(GlobalKeys["human_fight_hp"]), 300, 170)
        groups.draw(root_face)
        click_time +=1
        if click_time % 5 ==0:
            groups.update()


def Fight(root_surface, select_human):
    GlobalKeys["is_fight"] = 1
    t = threading.Thread(target=Fightone, args=(root_surface, select_human))
    t2 = threading.Thread(target=Fightsprite, args=(root_surface, select_human))
    t2.start()
    t.start()

def Level(hp_num,duanti_num, yuqi_num):
    """
    人物强化
    :param hp_num:
    :param duanti_num:
    :param yuqi_num:
    :return:
    """
    Human["player"].max_hp = int(hp_num) + int(Human["player"].max_hp)
    Human["player"].duanti = int(duanti_num) + int(Human["player"].duanti)
    Human["player"].yuqi = int(yuqi_num) + int(Human["player"].yuqi)

def StrongHuman(name,hp_num,duanti_num, yuqi_num):
    """
    其他人强化
    :param name:
    :param hp_num:
    :param duanti_num:
    :param yuqi_num:
    :return:
    """
    Human[name].max_hp = int(hp_num) + int(Human[name].max_hp)
    Human[name].duanti = int(duanti_num) + int(Human[name].duanti)
    Human[name].yuqi = int(yuqi_num) + int(Human[name].yuqi)

def StartWindow(root_surface):
    """
    开始界面
    :param root_surface:
    :return:
    """
    start_button = Zhc_Control.BaseButton("开始")
    root_surface.blit(start_button, (350, 400))
    pygame.event.set_blocked(pygame.KEYDOWN)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            if (350 <= event.pos[0] <= 430) and (400 <= event.pos[1] <= 440):
                print("开始按钮已经点击了", GlobalKeys['Count'])
                root_surface.blit(start_button, (351, 401))
                GlobalKeys["Count"] += 1
        if event.type == pygame.MOUSEBUTTONUP:
            if (350 <= event.pos[0] <= 430) and (400 <= event.pos[1] <= 440):
                pygame.event.set_allowed(pygame.KEYDOWN)
                GlobalKeys["StartPush"] = False
            root_surface.blit(start_button, (350, 400))


def MainWindow(root_surface):
    """
    主界面
    这里需要三个四个分界面，右下角的
    :param root_surface:
    :return:
    """

    # 绘制事件面板
    player_show = pygame.transform.scale(pygame.image.load("picture/background1.jpg"), (200, 600))
    root_surface.blit(player_show, (600, 0))
    DrewOnlyPlayerMain(root_surface)

    # 绘制菜单按钮
    menu_button = {
        "人物": [Zhc_Control.BaseButton("人物"), (600, 570)],
        "背包": [Zhc_Control.BaseButton("背包"), (650, 570)],
        "技能": [Zhc_Control.BaseButton("技能"), (700, 570)],
        "系统": [Zhc_Control.BaseButton("系统"), (750, 570)]
    }
    for i in menu_button.keys():
        root_surface.blit(menu_button[i][0], menu_button[i][1])

    # 绘制地图
    root_surface.blit(MapCase[MapCase["SelectMap"]], (0, 0))

    # 绘制另外的东西
    if GlobalKeys["DoSomething"] == 1:
        if GlobalKeys["DoSomethingDef"] == "ShowMessage":
            DrewHumanMessage(root_surface, GlobalKeys["DoSomethingData"])
        if GlobalKeys["DoSomethingDef"] == "fight":
            if GlobalKeys["is_fight"] == 0:
                Fight(root_surface, GlobalKeys["select_human"])

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            print(event.pos)
            # 获取点击事件的类别，根据类别调用相应函数
            get_type = ReturnPlaceType(MapPlace[MapCase["SelectMap"]], event.pos)

            # 类型为 0 说明是地图条状
            if get_type == 0:
                # 需要存一个地图，用以返回的时候用
                MapCase["LastMap"] = MapCase["SelectMap"]
                # 返回了地图的名字，并将地图的名字赋值给所选地图，将会在下一次刷新的时候进行变更
                MapCase["SelectMap"] = ReturnPlaceName(MapPlace[MapCase["SelectMap"]], event.pos)
            elif get_type == 1:
                # 获取名称，如果类型是0，那么会返回地图名称，如果类型是返回，那么会返回方法名称
                type_name = ReturnPlaceName(MapPlace[MapCase["SelectMap"]], event.pos)
                # 如果点击返回，那么将上一张地图设置为将要刷新的地图
                if type_name == "Back":
                    # 这里仅针对于属性面板的返回，用以返回上一层，并且关闭属性显示
                    print("按下了返回键", MapCase["LastMap"])
                    MapCase["SelectMap"] = MapCase["LastMap"]
                    GlobalKeys["DoSomething"] = 0
            elif get_type == 2:
                MapCase["LastMap"] = MapCase["SelectMap"]
                # 返回了地图的名字，并将地图的名字赋值给所选地图，将会在下一次刷新的时候进行变更
                MapCase["SelectMap"] = ReturnPlaceName(MapPlace[MapCase["SelectMap"]], event.pos)
                run_def = ReturnPlaceDef(MapPlace[MapCase["LastMap"]], event.pos)
                print("出发了函数是2", "run_def是", run_def)
                GlobalKeys["DoSomething"] = 1
                # 开始进行函数触发的判断
                if run_def[0] == "ShowMessage":
                    print("触发了函数showmessage")
                    GlobalKeys["DoSomethingDef"] = "ShowMessage"
                    GlobalKeys["DoSomethingData"] = run_def[1]
                    GlobalKeys["select_human"] = run_def[1]

                if run_def[0] == "fight":
                    print("触发了函数fight")
                    GlobalKeys["DoSomethingDef"] = "fight"
                    GlobalKeys["DoSomethingData"] = run_def[1]

            elif get_type == 3:
                run_def = ReturnPlaceDef(MapPlace[MapCase["SelectMap"]], event.pos)
                if run_def == "levelup":
                    Level(30,10,10)
                if run_def == "getstrong":
                    StrongHuman(GlobalKeys["select_human"],20,5,5)

def RunWindow():
    # 初始化界面
    pygame.init()

    root_surface = pygame.display.set_mode((800, 600))
    root_window = pygame.display
    root_window.set_caption("窗口")

    # 开始初始化人物,技能
    IniHuman()
    IniSkill()
    # 开始游戏主循环
    while True:
        pygame.time.Clock().tick(60)
        root_window.update()
        root_surface.fill((220, 220, 220))

        if GlobalKeys["StartPush"]:
            StartWindow(root_surface)
        else:
            MainWindow(root_surface)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()


if __name__ == '__main__':
    RunWindow()
